#include "IncidenceGraph.h"


const Vertex Vertex::Null = Vertex(-1, 0, 0);


const Edge Edge::Null = Edge(-1, -1, 0);


IncidenceGraph::IncidenceGraph()
{
}


IncidenceGraph::~IncidenceGraph()
{
}


void IncidenceGraph::AddVertex(int i, float x, float y)	
{
	if (ContainsVertex(i))
		return;

	if (i < 0)
		return;
	
	vertices.insert(make_pair(i, Vertex(i, x, y)));
}


void IncidenceGraph::RemoveVertex(int i)
{
	incidences.erase(i);
	vertices.erase(i);
}


bool IncidenceGraph::ContainsVertex(int i) const
{
	return vertices.find(i) != vertices.end();
}


Vertex IncidenceGraph::GetVertex(int i) const
{
	auto it = vertices.find(i);
	if (it == vertices.end())
		return Vertex::Null;
	else
		return it->second;
}


list<Vertex> IncidenceGraph::GetVertices() const
{
	auto l = list<Vertex>();
	for (auto it = vertices.begin(); it != vertices.end(); it++) {
		l.push_back(it->second);
	}
	return l;
}


void IncidenceGraph::SetVertex(int i, Vertex& vertex)
{
	vertices[i] = vertex;
}


int IncidenceGraph::VertexCount() const
{
	return vertices.size();
}


int IncidenceGraph::EdgeCount(int i) const
{
	auto n = 0;
	auto i_range = incidences.equal_range(i);
	for (auto it = i_range.first; it != i_range.second; it++) {
		if (it->second.i == i) n++;
	}
	return n;
}


void IncidenceGraph::AddDirectedEdge(int i, int j, double weight, bool addVertices)
{
	if (weight < 0)
		return;

	if (addVertices) {
		AddVertex(i);
		AddVertex(j);
	}
	
	auto i_range = incidences.equal_range(i);
	for (auto it = i_range.first; it != i_range.second; it++) {
		if (it->second.i == i && it->second.j == j)
			return;
	}

	incidences.insert(make_pair(i, Edge(i, j, weight)));
}


void IncidenceGraph::AddUndirectedEdge(int i, int j, double weight, bool addVertices)
{
	if (weight < 0)
		return;

	if (addVertices) {
		AddVertex(i);
		AddVertex(j);
	}

	AddDirectedEdge(i, j, weight, false);
	AddDirectedEdge(j, i, weight, false);
}


void IncidenceGraph::RemoveEdge(int i, int j)	
{
	auto i_range = incidences.equal_range(i);
	for (auto it = i_range.first; it != i_range.second; it++) {
		if (it->second.i == i && it->second.j == j) {
			incidences.erase(it);
			return;
		}
	}
}


void IncidenceGraph::SetEdge(int i, int j, double weight)
{
	auto i_range = incidences.equal_range(i);
	for (auto it = i_range.first; it != i_range.second; it++) {
		if (it->second.i == i && it->second.j == j)
			it->second.weight = weight;
	}
}


Edge IncidenceGraph::GetEdge(int i, int j) const
{
	auto i_range = incidences.equal_range(i);
	for (auto it = i_range.first; it != i_range.second; it++) {
		if (it->second.i == i && it->second.j == j)
			return it->second;
	}

	return Edge::Null;
}


list<Edge> IncidenceGraph::GetEdges(int i) const
{
	auto l = list<Edge>();

	auto i_range = incidences.equal_range(i);
	for (auto it = i_range.first; it != i_range.second; it++) {
		if (it->second.i == i)
			l.push_back(it->second);
	}

	return l;
}


list<Edge> IncidenceGraph::GetEdges() const
{
	auto l = list<Edge>();

	for (auto it = incidences.begin(); it != incidences.end(); it++) {
		l.push_back(it->second);
	}

	return l;
}


bool IncidenceGraph::ContainsEdge(int i, int j) const
{
	auto i_range = incidences.equal_range(i);
	for (auto it = i_range.first; it != i_range.second; it++) {
		if (it->second.i == i && it->second.j == j)
			return true;
	}

	return false;
}


int IncidenceGraph::EdgeCount() const
{
	return incidences.size();
}


void IncidenceGraph::Clear()
{
	vertices.clear();
	incidences.clear();
}
